/*
 * Copyright (c) 2007 jNetX.
 * http://www.jnetx.com
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * jNetX. You shall not disclose such Confidential Information and
 * shall use it only in accordance with the terms of the license
 * agreement you entered into with jNetX.
 *
 * $Id$
 */
package com.jnetx.javax.sip.header;

import com.jnetx.javax.sip.message.SIPMessage;

import javax.sip.header.Header;
import java.text.ParseException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author <a href="mailto:dparhonin@jnetx.ru">Dmitry Parhonin</a>
 * @version $Revision$
 */
public abstract class HeaderBase implements Header {
    private static final Log logger = LogFactory.getLog(HeaderBase.class);

    private final String name;
    private SIPMessage owner;

    protected boolean parsed;
    protected byte[] data = null;
    protected int start, end;

    protected HeaderBase(String name) {
        this.name = name;
        this.parsed = true;
    }

    protected HeaderBase(String name, byte[] data, int start, int end) {
        this.name = name;
        this.data = data;
        this.start = start;
        this.end = end;
        this.parsed = false;
    }

    /**
     * Gets the unique string name of this Header. A name constant is defined in each individual Header identifying each Header.
     *
     * @return the name of this specific Header.
     */
    public String getName() {
        return name;
    }

    public SIPMessage getOwner() {
        return owner;
    }

    public void setOwner(SIPMessage owner) {
        this.owner = owner;
    }

    public abstract Object clone();

    protected void cloneBase(HeaderBase source) {
        this.data = source.data;
        this.parsed = source.parsed;
        this.start = source.start;
        this.end = source.end;
    }

    public String toString() {
        final String result;
        if (data != null)
            result = name + ": " + new String(data, start, end - start);
        else {
            final StringBuilder sb = new StringBuilder();
            sb.append(name).append(':').append(' ').append(getValueAsString());
            getParametersAsString(sb);
            result = sb.toString();
            data = result.getBytes();
        }
        return result;
    }

    public final void parse() {
        if (!parsed) {
            parsed = true;
            doParse();
        }
    }

    protected abstract HeaderParser getParser();

    protected void doParse() {
        try {
            final Header[] headers = getParser().parse(this, data, start, end);
            if (headers.length > 1) {
                final SIPMessage owner = getOwner();
                if (owner != null)
                    for (int i = 1; i < headers.length; i++)
                        owner.addHeader(headers[i]);
                else
                    logger.warn("Information about additional headers of type '" + getName() + "' is lost during lazy parsing!");
            }
        } catch (ParseException e) {
        }
    }

    protected void invalidateHeaderData() {
        if (data != null) parse();
        data = null;
    }

    protected abstract String getValueAsString();

    protected StringBuilder getParametersAsString(StringBuilder sb) {
        return getParametersAsString(sb, ';');
    }

    protected StringBuilder getParametersAsString(StringBuilder sb, char delimiter) {
        return sb;
    }
}
/*
 * $Log$
 */